# TODO: Should differ between the toolchain and the target.
#       For example, we may want to use the arm-elf toolchain for both the
#       beagleboard and some other foo-board.

cmake_minimum_required(VERSION 2.8)

project(kernel)
set (PROJECT_NAME "kernel")
set (kernel_VERSION_MAJOR 1)
set (kernel_VERSION_MINOR 0)

# Enable extra languages, ASM is not included as default.
enable_language(ASM)

#
# A work around to properly set up AR and RANLIB. If we do this
# in the toolchain config files, it gets overwritten by cmake
# in the enable_language statements above.
#

set(CMAKE_AR ${TOOLCHAIN_AR})
set(CMAKE_RANLIB ${TOOLCHAIN_RANLIB})

#
# Kernel Sources
#

set(COMMON_SRC
  ${CMAKE_SOURCE_DIR}/kernel/src/boot.c
  ${CMAKE_SOURCE_DIR}/kernel/src/bootparam.c
  ${CMAKE_SOURCE_DIR}/kernel/src/vm.c
  ${CMAKE_SOURCE_DIR}/kernel/src/syscall.c
  ${CMAKE_SOURCE_DIR}/kernel/src/panic.c
  ${CMAKE_SOURCE_DIR}/kernel/src/stdio.c
  ${CMAKE_SOURCE_DIR}/kernel/src/string.c
  ${CMAKE_SOURCE_DIR}/kernel/src/stdlib.c
  ${CMAKE_SOURCE_DIR}/kernel/src/ctype.c
  ${CMAKE_SOURCE_DIR}/kernel/src/interrupt.c
  ${CMAKE_SOURCE_DIR}/kernel/src/heap.c
  ${CMAKE_SOURCE_DIR}/kernel/src/timer.c
  ${CMAKE_SOURCE_DIR}/kernel/src/process.c
  ${CMAKE_SOURCE_DIR}/kernel/src/elf.c
  ${CMAKE_SOURCE_DIR}/kernel/src/sync.c
  ${CMAKE_SOURCE_DIR}/kernel/src/device.c
  ${CMAKE_SOURCE_DIR}/kernel/src/idle.c
  ${CMAKE_SOURCE_DIR}/kernel/src/drivers/ramdisk.c
  ${CMAKE_SOURCE_DIR}/kernel/src/vfs/vfs.c
  ${CMAKE_SOURCE_DIR}/kernel/src/vfs/fat16.c
  ${CMAKE_SOURCE_DIR}/kernel/src/vfs/wfs.c
  ${CMAKE_SOURCE_DIR}/kernel/src/vfs/devfs.c)

#
# Include BSP file
#
if (DEFINED BSP)
  include(${BSP})
else (DEFINED BSP)
  message(FATAL_ERROR "BSP not specified")
endif(DEFINED BSP)

set(KERNEL_C_SRC ${COMMON_SRC} ${TARGET_C_SRC})

set(KERNEL_SRC ${TARGET_ASM_SRC} ${KERNEL_C_SRC})
set(KERNEL_C_FLAGS "-O1 -Wall -std=c99 -g ${TOOLCHAIN_C_FLAGS} ${TARGET_C_FLAGS}")
set(KERNEL_ASM_FLAGS "${TOOLCHAIN_ASM_FLAGS} ${TARGET_ASM_FLAGS}")
set(KERNEL_LINK_FLAGS "${TOOLCHAIN_LINK_FLAGS} ${TARGET_LINK_FLAGS}")
set(KERNEL_C_DEFS "${TOOLCHAIN_C_DEFS} ${TARGET_C_DEFS}")

#
# User-land
#
add_subdirectory(apps/)


include_directories(
  ${PROJECT_SOURCE_DIR}/include
  ${PROJECT_SOURCE_DIR}/kernel/include/)

if (NOT ${TOOLCHAIN_RT})
  add_subdirectory(rt)
  set(KERNEL_LIBS rt)
endif(NOT ${TOOLCHAIN_RT})

#
# Define the kernel target
#

add_executable(kernel.elf ${KERNEL_SRC})
set_target_properties(kernel.elf PROPERTIES
  LINK_FLAGS ${KERNEL_LINK_FLAGS})
set_source_files_properties(${KERNEL_C_SRC} PROPERTIES
  COMPILE_FLAGS "${KERNEL_C_FLAGS}")
set_source_files_properties(${KERNEL_C_SRC} PROPERTIES
  COMPILE_DEFINITIONS "${KERNEL_C_DEFS}")


set_source_files_properties(${TARGET_ASM_SRC} PROPERTIES
  COMPILE_FLAGS "${KERNEL_ASM_FLAGS}")
if (DEFINED KERNEL_LIBS)
  target_link_libraries(kernel.elf ${KERNEL_LIBS})
endif (DEFINED KERNEL_LIBS)

add_custom_command(TARGET kernel.elf
  POST_BUILD
  COMMAND ${TOOLCHAIN_OBJCOPY} -O binary  '${CMAKE_CURRENT_BINARY_DIR}/kernel.elf'
                                          '${CMAKE_CURRENT_BINARY_DIR}/kernel.bin')


#
# Optional Documentation
#

find_package(Doxygen)

if (DOXYGEN_FOUND)
  # Try to locate dot
  find_program(DOT_EXECUTABLE dot)
  if (DOT_EXECUTABLE)
    set(DOT_FOUND "YES")
    set(DOT_PATH "${DOT_EXECUTABLE}")
  else (DOT_EXECUTABLE)
    set(DOT_FOUND "NO")
    set(DOT_PATH "")
  endif (DOT_EXECUTABLE)

  # Configure the doxygen file
  set(DOXYGEN_CONFIG "${CMAKE_BINARY_DIR}/doxygen.config")

  configure_file( "${CMAKE_SOURCE_DIR}/config/doxygen.conf.in"
    "${DOXYGEN_CONFIG}"
    @ONLY)
  add_custom_target(docs ${DOXYGEN_EXECUTABLE} ${DOXYGEN_CONFIG}
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
endif (DOXYGEN_FOUND)
